package com.forever.thread.executor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;

import com.forever.thread.ThreadFactoryImpl;

/**
 * 线程池
 * 
 * @author forever
 * 
 */
public class ExecutorTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newSingleThreadExecutor();
		List<Future<String>> list = new ArrayList<Future<String>>();
		for (int i = 0; i < 10; i++) {
			Future<String> future = service.submit(new ExecutorTest.CallableTest(i));
			list.add(future);
		}
		if (null != list && list.size() > 0) {
			for (Future<String> item : list) {
				try {
					String result = item.get();
					System.out.println(result);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
			}
		}
		service.shutdown();

		ThreadFactory factory = new ThreadFactoryImpl();
		ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 5, TimeUnit.MINUTES,
				new ArrayBlockingQueue<Runnable>(5), factory, new CallerRunsPolicy()) {

			@Override
			protected void afterExecute(Runnable r, Throwable t) {
				super.afterExecute(r, t);
				printException(r, t);
			}

		};
		pool.execute(new Runnable() {

			@Override
			public void run() {
				Thread t = Thread.currentThread();
				System.out.print("\n");
				System.out.println("id:" + t.getId());
				System.out.println("name:" + t.getName());
				System.out.println("group:" + t.getThreadGroup().getName());
				System.out.println("state:" + t.getState().toString());
			}
		});
		pool.shutdown();
	}

	private static void printException(Runnable r, Throwable t) {
		if (t == null && r instanceof Future<?>) {
			try {
				Future<?> future = (Future<?>) r;
				if (future.isDone())
					future.get();
			} catch (CancellationException ce) {
				t = ce;
			} catch (ExecutionException ee) {
				t = ee.getCause();
			} catch (InterruptedException ie) {
				Thread.currentThread().interrupt(); // ignore/reset
			}
		}
		if (t != null)
			System.out.println(t.getMessage());
	}

	static class CallableTest implements Callable<String> {
		private int value;

		@Override
		public String call() throws Exception {
			return Math.round(Math.random() * 1000) + "--" + value;
		}

		public CallableTest(int value) {
			this.value = value;
		}
	}
}
